import React, { useState, useEffect } from "react"
import { useSafeAreaInsetsStyle } from "../../utils/useSafeAreaInsetsStyle"
import {
  View,
  ViewStyle,
  Text,
  ScrollView,
  SectionList,
  TouchableOpacity,
  ActivityIndicator,
} from "react-native"
import Animated, { Easing, FadeIn, FadeOut } from "react-native-reanimated"
import DatePicker from "react-native-date-picker"
import dayjs from "dayjs"
import { RouteProp, useFocusEffect, useNavigation, useRoute } from "@react-navigation/native"
import { scale } from "react-native-size-matters"
import { useAppDispatch, useAppSelector } from "app/redux/hooks"

//Icons
import { AntDesign } from "@expo/vector-icons"
import { Ionicons } from "@expo/vector-icons"

//Local Component imports
import { colors } from "app/theme"
import MainHeader from "app/components/MainHeader"
import { Button } from "app/components"
import { styles } from "./styles"
import { DropdownComponent } from "app/components/DropDownComponent"
import { SelectOptionButton } from "app/components/SelectableOption"
import AppointmentRepeatView from "./AppointmentRepeatView"

//function imports
import {
  setRoom,
  setError,
  setEtheraRooms,
  setDateCheckBox,
  setSelectedDates,
  setNumberOfWeeks,
  setBookingEndTime,
  setOtherLocations,
  setWeeklyCheckBox,
  setWeeklyRepeatGap,
  setAppointmentDate,
  setEtheraLocations,
  setBookingStartTime,
  setAppointmentLocation,
  resetAppointmentLocationScreen,
  populateSelectedDates,
  setHealthCheckBox,
  setMeetCheckBox,
  setZoomCheckBox,
  setSelectedClients,
  addServices,
  setStartTime,
  setEndTime,
  editDetails,
  setAppointmentStatus,
  setRoomCost,
  setAppointmentDetails,
} from "app/redux/slices/createAppointmentSlice"
import {
  getEtheraRooms,
  getOtherLocations,
  getEtheraLocations,
  getRoomCost,
} from "app/services/apis/location"
import {
  generateGetRoomsBody,
  generateRoomCostBody,
} from "app/services/helperFunctions/generateBody"
import { setLoader, setLocationLoader } from "app/redux/slices/loadingSlice"
import MakeLocationData from "./LocationData"
import { getAppointment } from "app/redux/actions/appointmentActions"
import { getAppointmentDetails } from "app/services/apis/getAppointment"
import { format, isPast, parse, parseISO } from "date-fns"
import { convertIn12HourFormat } from "app/services/helperFunctions/timeConverter"
import LoaderComponent from "app/components/Loader"
import { Dropdown } from "react-native-element-dropdown"
import { statusArray } from "app/constants/dateArray"

type Params = {
  item: any
}

interface RoomData {
  name: string
  id: string
}

export const EditAddAppointment = () => {
  const $bottomContainerInsets = useSafeAreaInsetsStyle(["bottom", "top"])

  const route = useRoute<RouteProp<Params>>()

  //Hooks
  const navigation = useNavigation()
  const dispatch = useAppDispatch()

  //Local States
  const [isFocus, setIsFocus] = useState(false)
  const [date, setDate] = useState(new Date())
  const [locationDropdown, setLocationDropdown] = React.useState(false)
  const [dates, setDates] = useState({
    show: false,
    type: "",
    date: "",
    start: "",
    end: "",
  })

  // This state is used to store the start time as a raw , nonFormatted time string,
  // ensuring that the minimum end time will always be greater than the start time in appointment Location screen
  const [minimumTime, setMinimunTime] = useState(null)
  const [maximumTime, setMaximumTime] = useState(null)
  const [loading, setLoading] = useState(true)
  const [roomData, setRoomData] = useState(null)
  //This state is needed in according to delete appointment on next screen
  const [id, setId] = useState("")
  //This state is needed in according to delete booking on next screen
  const [bookingId, setBookingId] = useState("")

  //retriving appointment state time , date and location etc
  const appointmentState = useAppSelector((state) => state?.createAppointment)
  const loadingState = useAppSelector((state) => state?.loading)

  //retriving current user details
  const providerState = useAppSelector((state) => state?.provider)

  const onPressWeekCheckBox = (newValue: any) => {
    //Checking if start_date is passed nothing can be editable except status
    !appointmentState?.datePassed && dispatch(setWeeklyCheckBox(newValue))
  }

  const onPressDateCheckBox = (newValue: any) => {
    //Checking if start_date is passed nothing can be editable except status
    !appointmentState?.datePassed && dispatch(setDateCheckBox(newValue))
  }

  const onPressRepeat = (number_of_weeks) => {
    //Checking if start_date is passed nothing can be editable except status
    !appointmentState?.datePassed && dispatch(setNumberOfWeeks({ number_of_weeks }))
  }

  const onPressRepeatGap = (weeklyRepeatGap) => {
    //Checking if start_date is passed nothing can be editable except status
    !appointmentState?.datePassed && dispatch(setWeeklyRepeatGap({ weeklyRepeatGap }))
  }

  const onSelectDates = (date) => {
    //Checking if start_date is passed nothing can be editable except status
    !appointmentState?.datePassed && dispatch(setSelectedDates({ date }))
  }

  const onPressLocation = (item) => {
    dispatch(setAppointmentLocation(item))
    setLocationDropdown(!locationDropdown)
    setRoomData(null)
    dispatch(setRoomCost("0:00"))
    // in case user change its location from other to ethera after pressing weeklyRepeat then weeklyrepeat should be reset
    dispatch(setWeeklyCheckBox(false))
  }

  const onNextPress = () => {
    //To reset weeklyReapetGap and selected Dates In case User select and deselect weekly or date checkbox
    if (!appointmentState?.weeklyCheckbox && !appointmentState?.dateCheckBox) {
      //TODO reset selected dates too
      dispatch(setWeeklyRepeatGap({ weeklyRepeatGap: null }))
      dispatch(setNumberOfWeeks({ number_of_weeks: null }))
    }

    if (appointmentState?.appointmentLocationType !== "ethera") {
      if (
        !appointmentState?.appointmentLocation ||
        !appointmentState?.appointmentDate ||
        (appointmentState?.weeklyCheckbox &&
          (!appointmentState?.weeklyRepeatGap || !appointmentState?.number_of_weeks))
      ) {
        dispatch(setError("is required"))
        return
      } else {
        dispatch(setError(""))
        // @ts-ignore
        navigation.navigate("EditAppointmentDetails", {
          minimumTime: minimumTime,
          maximumTime: maximumTime,
          id: id,
          bookingId: bookingId,
        })
      }
    } else if (appointmentState?.appointmentLocationType === "ethera") {
      if (
        !appointmentState?.appointmentLocation ||
        !appointmentState?.appointmentDate ||
        !(appointmentState?.room || roomData) ||
        !appointmentState?.bookingStartTime ||
        !appointmentState?.bookingEndTime
      ) {
        dispatch(setError("is required"))
        return
      } else {
        dispatch(setError(""))
        // @ts-ignore
        navigation.navigate("EditAppointmentDetails", {
          minimumTime: minimumTime,
          maximumTime: maximumTime,
          id: id,
          bookingId: bookingId,
        })
      }
    }
  }

  //Fetching ETHERA LOCATIONS to populate location dropdown
  useEffect(() => {
    dispatch(setLocationLoader(true))
    getEtheraLocations()
      .then((result: any) => {
        dispatch(setLocationLoader(false))
        dispatch(setEtheraLocations(result?.data))
      })
      .catch((error: any) => {
        dispatch(setLocationLoader(true))
        console.log("error in fetching ethera locations", error)
      })
  }, [])

  //Fetching OTHER LOCATIONS to populate location dropdown
  useEffect(() => {
    if (providerState?.provider?.id) {
      dispatch(setLocationLoader(true))
      getOtherLocations(providerState?.provider?.id)
        .then((result: any) => {
          dispatch(setLocationLoader(false))
          dispatch(setOtherLocations(result?.data))
        })
        .catch((error: any) => {
          dispatch(setLocationLoader(false))
          console.log("error in fetching other locations", error)
        })
    }
  }, [providerState])

  useEffect(() => {
    if (
      appointmentState?.appointmentLocation !== "" &&
      appointmentState?.appointmentLocationType === "ethera"
    ) {
      dispatch(setLoader(true))
      let params = generateGetRoomsBody(appointmentState, providerState)
      getEtheraRooms(params)
        .then((result: any) => {
          dispatch(setEtheraRooms(result?.data))
          dispatch(setRoom({ label: "", value: "" }))
          dispatch(setLoader(false))
        })
        .catch((error: any) => {
          console.log("error in fetching ethera rooms", error)
          dispatch(setLoader(false))
        })
    }
  }, [
    appointmentState?.appointmentLocation,
    appointmentState?.bookingStartTime,
    appointmentState?.bookingEndTime,
    appointmentState?.appointmentDate,
    appointmentState?.selectedDatesArray,
  ])

  useEffect(() => {
    return () => {
      console.log("unmounts")
      dispatch(setError(""))
      dispatch(resetAppointmentLocationScreen())
    }
  }, [])

  //Populating existing values
  useEffect(() => {
    getAppointmentDetails(route?.params?.id)
      .then((result: any) => {
        setLoading(false)
        console.log("result", JSON.stringify(result?.data, null, 2))
        dispatch(setAppointmentDetails(result?.data))
        dispatch(setAppointmentStatus(result?.data?.status))
        setId(result?.data?.id)
        if (result?.data?.booking) {
          setBookingId(result?.data?.booking?.id)
        }
        let location = {
          name: result?.data?.booking
            ? result?.data?.booking?.location?.name
            : result?.data?.provider_location?.name,
          id: result?.data?.booking
            ? result?.data?.booking?.location?.id
            : result?.data?.provider_location?.id,
          type: result?.data?.booking ? "ethera" : "other",
        }
        //Populating location
        dispatch(setAppointmentLocation(location))
        const formattedDate = new Date(result?.data?.start_date * 1000).toLocaleDateString("en-GB")
        const formattedISODate = parseISO(new Date(result?.data?.start_date * 1000).toISOString())
        const checkDate = isPast(formattedISODate)
        console.log("datePassed", checkDate)
        dispatch(editDetails(checkDate))

        //Populating Appointment StartDate
        dispatch(setAppointmentDate({ appointmentDate: formattedDate }))
        setDates((prev) => {
          return {
            ...prev,
            date: formattedDate,
            type: "",
            show: false,
          }
        })
        //Populating Appointment weekly_repeat
        if (result?.data?.weekly_repeat) {
          dispatch(setWeeklyCheckBox(true))
          dispatch(setWeeklyRepeatGap({ weeklyRepeatGap: result?.data?.weekly_repeat_gap }))
          dispatch(setNumberOfWeeks({ number_of_weeks: result?.data?.number_of_weeks }))
        }
        //Populating Appointment select_dates
        if (result?.data?.select_dates === true) {
          dispatch(setDateCheckBox(true))
          dispatch(populateSelectedDates(result?.data?.selected_dates))
        }
        //Populating appointment start and end time
        if (!result?.data?.booking) {
          const formattedStartTime = convertIn12HourFormat(result?.data?.start_time)
          dispatch(setStartTime({ startTime: formattedStartTime }))
          const formattedEndTime = convertIn12HourFormat(result?.data?.end_time)
          dispatch(setEndTime({ endTime: formattedEndTime }))
        }

        //Populating booking and appointment start and end time if booking exist
        if (result?.data.booking) {
          if (result?.data?.booking?.selected_dates.length) {
            dispatch(setDateCheckBox(true))
            dispatch(populateSelectedDates(result?.data?.booking?.selected_dates))
          }
          const formattedStartTime = convertIn12HourFormat(result?.data?.booking?.start_time)
          dispatch(setBookingStartTime({ bookingStartTime: formattedStartTime }))
          dispatch(setStartTime({ startTime: formattedStartTime }))

          const formattedEndTime = convertIn12HourFormat(result?.data?.booking?.end_time)
          dispatch(setBookingEndTime({ bookingEndTime: formattedEndTime }))
          dispatch(setEndTime({ endTime: formattedEndTime }))

          const parsedstartTime = parse(
            result?.data?.booking?.start_time,
            "HH:mm:ss",
            new Date(result?.data?.start_date * 1000),
          )
          const parsedEndTime = parse(
            result?.data?.booking?.end_time,
            "HH:mm:ss",
            new Date(result?.data?.start_date * 1000),
          )
          setMinimunTime(parsedstartTime)
          setMaximumTime(parsedEndTime)
          //As this room is booked and not in Ethera response so here storing them
          setRoomData(result?.data?.booking?.room)
          dispatch(setRoomCost(result?.data?.booking?.room_cost))
        }

        //Populating telehealth
        if (result?.data?.telehealth) {
          dispatch(setHealthCheckBox(true))
          if (result?.data?.google) {
            dispatch(setMeetCheckBox(true))
          } else if (result?.data?.zoom) dispatch(setZoomCheckBox(true))
        }

        //Populating clients and thier services
        if (result?.data?.provider_location) {
          result?.data?.appointment_services?.map((item) => {
            dispatch(
              setSelectedClients({
                name: item?.id?.first_name + item?.id?.last_name,
                id: item?.id?.id,
              }),
            )
            item?.services?.map((service) => {
              dispatch(
                addServices({
                  id: item?.id?.id,
                  services: {
                    id: service?.service?.id,
                    name: service?.service?.service,
                    fee: service?.service?.fee,
                  },
                }),
              )
            })
          })
        }
      })
      .catch((error: any) => {
        setLoading(false)
        console.log("error in fetching appointment details", error)
      })
  }, [])

  //Fetching Room cost against each room selected
  useEffect(() => {
    if (appointmentState?.roomId) {
      let body = generateRoomCostBody(appointmentState)
      getRoomCost(body)
        .then((result: any) => {
          dispatch(setRoomCost(result?.data?.room_cost))
          console.log("result in room cost", JSON.stringify(result, null, 2))
        })
        .catch((error: any) => {
          console.log("error in room cost", JSON.stringify(error, null, 2))
        })
    }
  }, [appointmentState?.roomId])

  const renderItem = (item: any) => {
    return (
      <View style={[styles.item, { alignItems: "flex-start", marginLeft: scale(10) }]}>
        <Text style={styles.weekText1}>{item.label}</Text>
      </View>
    )
  }

  const LOCATIONDATA = MakeLocationData()

  return (
    <View style={[$container, $bottomContainerInsets]}>
      {loading ? (
        <View style={styles.overlay}>
          <LoaderComponent />
        </View>
      ) : (
        <>
          <MainHeader />
          <View
            style={{
              flexDirection: "row",
              alignItems: "center",
              justifyContent: "space-between",
            }}
          >
            <View style={styles.infoContainer}>
              <Text style={styles.infoText}>Edit Appointment Location</Text>
            </View>
            {appointmentState?.datePassed && (
              <Dropdown
                disable={appointmentState?.status === 2}
                dropdownPosition="bottom"
                itemContainerStyle={{ padding: 0 }}
                style={[
                  styles.repeatView2,
                  { marginRight: scale(15), width: scale(100) },
                  isFocus && { borderColor: "black" },
                ]}
                activeColor={colors.dullGreen}
                placeholderStyle={styles.placeholderStyle}
                selectedTextStyle={styles.placeholderStyle}
                data={statusArray.map((item) => ({
                  label: item?.label,
                  value: item?.value,
                }))}
                maxHeight={200}
                labelField="label"
                valueField="value"
                placeholder={"..."}
                value={appointmentState?.status}
                onFocus={() => setIsFocus(true)}
                onBlur={() => setIsFocus(false)}
                onChange={(item) => {
                  dispatch(setAppointmentStatus(item.value))
                  // setIsFocus(false)
                }}
                renderItem={renderItem}
              />
            )}
          </View>

          <ScrollView
            style={{ flex: 1 }}
            contentContainerStyle={{ paddingHorizontal: 20, paddingBottom: 100 }}
          >
            <View style={{ paddingVertical: 5 }}>
              <Text style={styles.label}>Location</Text>
              {loadingState?.locationLoader ? (
                <View style={styles.container}>
                  <LoaderComponent />
                </View>
              ) : (
                <SelectOptionButton
                  selectedText={
                    appointmentState?.appointmentLocation !== ""
                      ? appointmentState?.appointmentLocation
                      : "Location"
                  }
                  onPress={() => {
                    //Checking if start_date is passed nothing can be editable except status
                    !appointmentState?.datePassed && setLocationDropdown(!locationDropdown)
                  }}
                  icon={<Ionicons name="location-outline" size={scale(20)} color="black" />}
                />
              )}

              {locationDropdown ? (
                <Animated.View
                  entering={FadeIn.duration(200).easing(Easing.ease)}
                  exiting={FadeOut.duration(200).easing(Easing.ease)}
                  style={styles.locationView}
                >
                  <SectionList
                    sections={LOCATIONDATA}
                    keyExtractor={(item, index) => `key-${index}`}
                    renderItem={({ item }: any) => {
                      return (
                        <TouchableOpacity
                          style={styles.locationItem}
                          onPress={() => onPressLocation(item)}
                        >
                          <View>
                            <Text style={{ color: colors.black }}>{item?.name}</Text>
                          </View>
                        </TouchableOpacity>
                      )
                    }}
                    renderSectionHeader={({ section: { title, checkLength } }) =>
                      checkLength && <Text style={styles.locationTitle}>{title}</Text>
                    }
                  />
                </Animated.View>
              ) : null}
              {appointmentState?.error && !appointmentState?.appointmentLocation ? (
                <Text style={{ color: "red", marginTop: scale(2) }}>
                  Location {appointmentState?.error}
                </Text>
              ) : null}
            </View>
            <View style={{ paddingVertical: 5 }}>
              <Text style={styles.label}>Date</Text>
              <SelectOptionButton
                selectedText={dates?.date !== "" ? appointmentState?.appointmentDate : "Date"}
                onPress={() => {
                  //Checking if start_date is passed nothing can be editable except status
                  !appointmentState?.datePassed &&
                    setDates((prev) => {
                      return {
                        ...prev,
                        type: "date",
                        show: !prev?.show,
                      }
                    })
                }}
                icon={<AntDesign name="calendar" size={scale(20)} color="black" />}
              />
              {appointmentState?.error && !appointmentState?.appointmentDate ? (
                <Text style={{ color: "red", marginTop: scale(2) }}>
                  Date {appointmentState?.error}
                </Text>
              ) : null}
            </View>

            <AppointmentRepeatView
              onPressWeekCheckBox={onPressWeekCheckBox}
              onPressDateCheckBox={onPressDateCheckBox}
              onPressRepeatGap={onPressRepeatGap}
              onPressRepeat={onPressRepeat}
              onSelectDates={onSelectDates}
              dateCheckBox={appointmentState?.dateCheckBox}
              weekCheckbox={appointmentState?.weeklyCheckbox}
              error={appointmentState?.error}
            />
            {appointmentState?.appointmentLocationType === "ethera" && (
              <>
                <View style={{ paddingVertical: 5, flexDirection: "row" }}>
                  <View style={{ flex: 1, marginRight: 5 }}>
                    <Text style={styles.label}>Start Time</Text>
                    <SelectOptionButton
                      selectedText={
                        appointmentState?.bookingStartTime
                          ? appointmentState?.bookingStartTime
                          : "Start Time"
                      }
                      onPress={() => {
                        //Checking if start_date is passed nothing can be editable except status
                        !appointmentState?.datePassed &&
                          appointmentState?.bookingEndTime !== "" &&
                          dispatch(setBookingEndTime("")) &&
                          setDates((prev) => {
                            return {
                              ...prev,
                              type: "start",
                              show: true,
                            }
                          })
                      }}
                      icon={<AntDesign name="calendar" size={24} color="black" />}
                    />
                  </View>
                  <View style={{ flex: 1, marginLeft: 5 }}>
                    <Text style={styles.label}>End Time</Text>
                    <SelectOptionButton
                      selectedText={
                        appointmentState?.bookingEndTime
                          ? appointmentState?.bookingEndTime
                          : "End Time"
                      }
                      onPress={() =>
                        //Checking if start_date is passed nothing can be editable except status
                        !appointmentState?.datePassed &&
                        setDates((prev) => {
                          return {
                            ...prev,
                            type: "end",
                            show: !prev?.show,
                          }
                        })
                      }
                      icon={<AntDesign name="calendar" size={24} color="black" />}
                    />
                  </View>
                </View>
                {appointmentState?.error &&
                (!appointmentState?.bookingStartTime || !appointmentState?.bookingEndTime) ? (
                  <Text style={{ color: "red", marginTop: scale(2) }}>
                    Time {appointmentState?.error}
                  </Text>
                ) : null}
              </>
            )}

            {appointmentState?.appointmentLocationType === "ethera" && (
              <View style={{ paddingVertical: scale(8) }}>
                <Text style={styles.label}>Rooms</Text>
                {loadingState?.loader ? (
                  <View style={styles.container}>
                    <ActivityIndicator color={colors.orange} />
                  </View>
                ) : (
                  <DropdownComponent
                    search
                    searchPlaceholder="Search Room"
                    placeholder={roomData?.name ? roomData?.name : "Search Room"}
                    onChange={(text) => {
                      dispatch(setRoom({ room: text }))
                    }}
                    data={appointmentState?.etheraRooms?.map(
                      (room: { name: string; id: string }) => ({
                        label: room?.name,
                        value: room?.id,
                      }),
                    )}
                    value={appointmentState?.roomId}
                    //Checking if start_date is passed nothing can be editable except status
                    disable={appointmentState?.datePassed}
                  />
                )}
                {appointmentState?.error && !appointmentState?.room ? (
                  <Text style={{ color: "red", marginTop: scale(2) }}>
                    Room {appointmentState?.error}
                  </Text>
                ) : null}
                <View style={styles.roomCost}>
                  <Text style={styles.costLabel}>Room Cost</Text>
                  <View style={styles.roomCostView}>
                    <Text style={styles.roomCostText}>$</Text>
                    <Text style={styles.roomCostText}>{appointmentState?.roomCost}</Text>
                  </View>
                </View>
              </View>
            )}

            <View style={{ marginVertical: 44 }}>
              {appointmentState?.appointmentLoader === true ? (
                <View style={styles.btn}>
                  <ActivityIndicator color={colors.orange} />
                </View>
              ) : (
                <Button preset="filled" text="Next" onPress={onNextPress} />
              )}

              <Button
                text="Back"
                textStyle={{ color: colors.brown }}
                onPress={() => navigation.goBack()}
              />
            </View>
          </ScrollView>
          <DatePicker
            locale="en"
            modal
            mode={dates.type === "date" ? "date" : "time"}
            open={dates.show}
            date={date}
            minuteInterval={15}
            minimumDate={
              (dates.type === "end" && minimumTime) || (dates.type === "date" && new Date())
            }
            onConfirm={(date) => {
              let formatedDate = dayjs(new Date(date)).format("DD/MM/YYYY")
              let formatedTime = dayjs(new Date(date)).format("h:mm A")
              if (dates.type === "date") {
                dispatch(setAppointmentDate({ appointmentDate: formatedDate }))
                setDates((prev) => {
                  return {
                    ...prev,
                    date: formatedDate,
                    type: "",
                    show: false,
                  }
                })
              }

              if (dates.type === "start") {
                dispatch(setBookingStartTime({ bookingStartTime: formatedTime }))
                setMinimunTime(date)
                setDates((prev) => {
                  return {
                    ...prev,
                    start: formatedTime, //formatedDate,
                    type: "",
                    show: false,
                  }
                })
              }

              if (dates.type === "end") {
                dispatch(setBookingEndTime({ bookingEndTime: formatedTime }))
                setMaximumTime(date)
                setDates((prev) => {
                  return {
                    ...prev,
                    end: formatedTime, //formatedDate,
                    type: "",
                    show: false,
                  }
                })
              }

              setDate(date)
            }}
            onCancel={() => {
              setDates((prev) => {
                return {
                  ...prev,
                  show: false,
                }
              })
            }}
          />
        </>
      )}
    </View>
  )
}

const $container: ViewStyle = {
  flex: 1,
  backgroundColor: colors.background,
}
